<script lang="ts" setup>
import { ref, reactive, watchEffect, onMounted, computed, watch } from 'vue'
import { FormInstance, FormRules, dayjs } from 'element-plus'
import { ElMessage } from 'element-plus'
import { useWindowSize } from '@vueuse/core'
import { LoginRequestData, LoginResponseData } from '@/api/login/types/login'
import { wxlogin } from '@/api/login'
import { validatePhone } from '@/utils/formvalidate'
import { useRouter } from 'vue-router'
import { useUserStore } from '@/store/modules/user'
import { useSMS } from '@/hooks/useSMS'
import { getComId, setComId } from '@/utils/cache/cookies'
import { useTabStore } from '@/store/modules/tab'
// 登录类型状态，'standard'为普通登录，'qrcode'为二维码登录
const loginType = ref('qrcode')
const router = useRouter()
const dialogVisible = ref<boolean>(false)
const tabStore = useTabStore()
/** 监听页面大小 改变表单size */
const enum SizeType {
  Large = 'large',
  Default = 'default'
}
const { width } = useWindowSize()
const loginFormSize = ref<SizeType>(SizeType.Default)
watchEffect(() => {
  if (width.value >= 1920) {
    loginFormSize.value = SizeType.Large
  } else {
    loginFormSize.value = SizeType.Default
  }
})

interface FormState {
  form: LoginRequestData
  isLoading: boolean
  rule: FormRules
  disable: boolean
}
const createFormState = (): FormState => {
  return reactive({
    form: {
      phone: '',
      code: ''
    },
    isLoading: false,
    disable: false,
    rule: {
      phone: [{ validator: validatePhone, trigger: 'blur' }],
      code: [{ required: true, message: '请输入验证码', trigger: 'blur' }]
    }
  })
}
// 创建两个独立的状态
const loginState = createFormState()
const bindingState = createFormState()
/** 表单基础逻辑 */
const formRef = ref<FormInstance | null>(null)
const bindingFormRef = ref<FormInstance | null>(null)
// 对于登录表单
const { sendSMSLabel: loginSendSMSLabel, handleSendSMS: loginHandleSendSMS } = useSMS(loginState)
// 对于绑定表单
const { sendSMSLabel: bindingSendSMSLabel, handleSendSMS: bindingHandleSendSMS } =
  useSMS(bindingState)
const LoginButtonLabel = computed(() => {
  if (loginState.isLoading) {
    return '登录中...'
  } else {
    return '登录'
  }
})
const BindingButtonLabel = computed(() => {
  if (bindingState.isLoading) {
    return '绑定中...'
  } else {
    return '绑定'
  }
})

/** 登录表单逻辑 */
const handleLogin = () => {
  sessionStorage.clear()
  formRef.value?.validate((valid) => {
    if (valid) {
      loginState.isLoading = true
      useUserStore()
        .login({
          ...loginState.form
        })
        .then(() => {
          ElMessage.success('登录成功!')
          loginState.isLoading = false
          router.push({ path: tabStore.visitedViews[tabStore.visitedViews.length - 1].path })
        })
        .catch(() => {
          loginState.form.code = ''
        })
        .finally(() => {
          loginState.isLoading = false
        })
    }
  })
}
const handleBinding = () => {
  sessionStorage.clear()
  bindingFormRef.value?.validate((valid) => {
    if (valid) {
      bindingState.isLoading = true
      wxlogin({
        ...bindingState.form,
        openId: openId.value
      })
        .then(() => {
          ElMessage.success('绑定成功!')
          bindingState.isLoading = false
          dialogVisible.value = false
        })
        .finally(() => {
          bindingState.isLoading = false
        })
    }
  })
}
const resetBindingForm = () => {
  bindingFormRef.value?.resetFields()
  dialogVisible.value = false
}
/** 微信登录 */
const comId = ref(getComId() ?? '')
const websock = ref<WebSocket | null>(null)
const timeoutId = ref<NodeJS.Timeout>()
const serverTimeoutId = ref<NodeJS.Timeout>()
const disconnectTimeoutId = ref<NodeJS.Timeout>()
const time = ref<number>(50000)
const lockReconnect = ref<boolean>(false) //是否真正建立连接
const openId = ref<string>('')
const websockstate = ref<boolean>(true)
onMounted(() => {
  sessionStorage.clear()
  if (comId.value === '') {
    let code = '' // 在循环外声明code
    for (let i = 1; i <= 6; i++) {
      const num = Math.floor(Math.random() * 10)
      code += num.toString() // 确保num是字符串
    }
    comId.value = dayjs().format('YYYYMMDDHHmmss') + code
    setComId(comId.value)
  }
  wxInit()
  initWebSocket()
})

const websocketonopen = () => {
  start()
}
const websocketonerror = () => {
  //错误连接websoket
  //重连
  comId.value = getComId() ?? ''
  //重连
  if (comId.value !== '') {
    reconnect()
  }
}
const websocketonmessage = (e: MessageEvent) => {
  //收到服务器信息，心跳重置
  reset()
  console.log('e:', e)
  const info = JSON.parse(e.data)
  if (info.code == '1') {
    ElMessage({
      message: info.data,
      type: 'warning'
    })
    wxInit()
  } else if (info.code == '0') {
    const param: LoginResponseData = info.data
    useUserStore()
      .wxLogin(param)
      .then(() => {
        // 重定向对象不存在则返回顶层路径
        router.replace({ path: '/' })
      })
  } else if (info.code == '404') {
    openId.value = info.data
    dialogVisible.value = true
    ElMessage({
      message: '没有账号信息',
      type: 'warning'
    })
    wxInit()
  }
}
const websocketclose = () => {
  //关闭websoket  当切换为表单登录
  comId.value = getComId() ?? ''
  //重连
  if (comId.value !== '') {
    reconnect()
  }
}
const reset = () => {
  //重置心跳
  //清除时间
  clearTimeout(timeoutId.value)
  clearTimeout(serverTimeoutId.value)
  //重启心跳
  start()
}
const start = () => {
  clearTimeout(timeoutId.value)
  clearTimeout(serverTimeoutId.value)
  timeoutId.value = setTimeout(() => {
    if (comId.value != '') {
      //这里发送一个心跳，后端收到后，返回一个心跳消息，
      if (websock.value?.readyState == 1) {
        //如果连接正常
        websock.value?.send(JSON.stringify({ comId: comId.value }))
      } else {
        //否则重连
        reconnect()
      }
    } else {
      websock.value?.close()
    }
    serverTimeoutId.value = setTimeout(() => {
      websock.value?.close()
    }, time.value)
  }, time.value)
}
const reconnect = () => {
  if (lockReconnect.value) return
  if (websock.value?.readyState !== 1) {
    lockReconnect.value = true
    disconnectTimeoutId.value = setTimeout(() => {
      initWebSocket()
      lockReconnect.value = false
    }, 2000)
  }
}
const wxInit = () => {
  const WxLogin = window['WxLogin'] // 确保 WxLogin 可用
  new WxLogin({
    self_redirect: true,
    id: 'qrcode_container',
    appid: 'wx185916925c848edf',
    scope: 'snsapi_login',
    redirect_uri: encodeURIComponent(import.meta.env.VITE_API + 'WxCallBack'),
    state: comId.value,
    style: 'black',
    href: 'https://admin.xiaoyuchuxing.com/MWTXHT/impowerBox.css'
  })
}
const initWebSocket = () => {
  websock.value = new WebSocket(import.meta.env.VITE_WebSocket + 'token=' + comId.value)
  websock.value.onopen = websocketonopen
  websock.value.onerror = websocketonerror
  websock.value.onmessage = websocketonmessage
  websock.value.onclose = websocketclose
}
watch(loginType, (loginType) => {
  if (loginType === 'standard') {
    websockstate.value = false
    websock.value?.close()
    lockReconnect.value = true
  } else {
    websockstate.value = true
    wxInit()
    initWebSocket()
  }
})
watchEffect(() => {
  if (!websockstate.value) {
    lockReconnect.value = true
    websock.value?.close()
  }
})
</script>

<template>
  <div class="login-container">
    <div class="left-container">
      <!-- 这里可以放置背景图和Logo -->
      <div class="background-image-container">
        <picture>
          <source media="(min-width: 1920px)" srcset="@/assets/login/large-logo.png" />
          <source media="(min-width: 1440px)" srcset="@/assets/login/medium-logo.png" />
          <img src="@/assets/login/small-logo.png" alt="Logo" class="logo" />
        </picture>
      </div>
    </div>
    <div class="right-container">
      <!-- 登录表单 -->
      <div class="login-form-wrapper">
        <div class="login-title">登录到</div>
        <div class="login-title">小鱼换电租车客服后台</div>
        <div class="login-type-switch">
          <span :class="{ active: loginType === 'qrcode' }" @click="loginType = 'qrcode'"
            >二维码登录</span
          >
          <span :class="{ active: loginType === 'standard' }" @click="loginType = 'standard'"
            >验证码登录</span
          >
        </div>
        <div v-show="loginType === 'qrcode'">
          <div id="qrcode_container" />
        </div>
        <div v-show="loginType === 'standard'" h-404 flex>
          <el-form
            :model="loginState.form"
            ref="formRef"
            :size="loginFormSize"
            :rules="loginState.rule"
            mt-40
          >
            <!-- 用户名输入 -->
            <el-form-item prop="phone">
              <el-input v-model="loginState.form.phone" placeholder="请输入登录手机号">
                <template #prefix>
                  <SvgIcon name="phone" />
                </template>
              </el-input>
            </el-form-item>
            <!-- 密码输入 -->
            <el-form-item prop="code">
              <el-input v-model="loginState.form.code" placeholder="请输入验证码" show-password>
                <template #prefix>
                  <SvgIcon name="password" />
                </template>
                <template #suffix>
                  <el-button
                    link
                    @click="loginHandleSendSMS(formRef)"
                    :disabled="loginState.disable"
                    v-html="loginSendSMSLabel"
                  />
                </template>
              </el-input>
            </el-form-item>
            <!-- 登录按钮 -->
            <el-form-item>
              <el-button
                type="primary"
                @click="handleLogin"
                w-full
                :loading="loginState.isLoading"
                >{{ LoginButtonLabel }}</el-button
              >
            </el-form-item>
          </el-form>
        </div>
        <el-dialog v-model="dialogVisible">
          <el-form
            :model="bindingState.form"
            ref="bindingFormRef"
            :size="loginFormSize"
            :rules="bindingState.rule"
          >
            <!-- 用户名输入 -->
            <el-form-item prop="phone" label="手机号:">
              <el-input v-model="bindingState.form.phone" placeholder="请输入登录手机号">
                <template #prefix>
                  <SvgIcon name="phone" />
                </template>
              </el-input>
            </el-form-item>
            <!-- 密码输入 -->
            <el-form-item prop="code" label="验证码:">
              <el-input v-model="bindingState.form.code" placeholder="请输入验证码" show-password>
                <template #prefix>
                  <SvgIcon name="password" />
                </template>
                <template #suffix>
                  <el-button
                    link
                    @click="bindingHandleSendSMS(bindingFormRef)"
                    :disabled="bindingState.disable"
                    v-html="bindingSendSMSLabel"
                  />
                </template>
              </el-input>
            </el-form-item>
          </el-form>
          <template #footer>
            <el-button plain @click="resetBindingForm">取消</el-button>
            <el-button type="primary" @click="handleBinding" :loading="bindingState.isLoading">{{
              BindingButtonLabel
            }}</el-button>
          </template>
        </el-dialog>
      </div>
    </div>
  </div>
</template>

<style scoped>
.login-container {
  display: flex;
  align-items: stretch;
  height: 100vh;
  background-color: var(--xy-white-color);
}

.left-container {
  flex: 1.5;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  position: relative; /* 为Logo定位做准备 */
}

.background-image-container {
  width: 100%;
  max-width: 800px; /* 或您希望的最大宽度 */
  height: 100%; /* 按照右侧表单的高度进行调整 */
  background-image: url('@/assets/login/background.png');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}

.logo {
  position: absolute;
  left: 15%; /* 或者您想要的具体数值 */
  top: 7%; /* 根据需求调整 */
  max-width: 248px; /* Adjust logo size as needed */
  height: auto;
  object-fit: contain;
}

.right-container {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
}

.login-form-wrapper {
  width: 100%;
  max-width: 440px; /* Adjust the form width as needed */
  padding: 20px;
  background: var(--xy-white-color);
}

.login-title {
  font-size: 38px;
  font-weight: 600;
  color: var(--xy-normal-text-color);
}
.login-type-switch {
  margin-top: 60px;
  margin-bottom: 40px;
}
.login-type-switch span {
  cursor: pointer;
  line-height: 28px;
  font-size: 20px;
  font-weight: 400;
  color: var(--xy-normal-text-color);
  position: relative; /* Required for absolute positioning of ::after */
  margin-bottom: 10px; /* Leave space for the color block */
  z-index: 0;
}
.login-type-switch span:last-child {
  margin-left: 40px;
}
.login-type-switch span::after {
  content: '';
  display: block;
  height: 10px;
  width: 0;
  background: linear-gradient(
    to right,
    var(--xy-primary-color),
    #fff
  ); /* Gradient from left to right */
  position: absolute;
  left: 50%;
  bottom: -3px;
  transition:
    width 0.3s ease,
    left 0.3s ease; /* Smooth transition for the color block */
  z-index: -1;
}
.login-type-switch .active {
  font-weight: 500;
}
.login-type-switch .active::after {
  width: 100%; /* Full width of the text */
  left: 0; /* Align with the left edge of the text */
}
/* .svg-icon {
  width: 20px;
  height: 20px;
} */
/* Responsive adjustments */
@media (max-width: 768px) {
  .left-container,
  .logo {
    display: none; /* Hide the aside and logo */
  }
  .right-container {
    justify-content: center;
    align-items: center;
    height: 100vh;
    width: 100%;
  }
  .login-form-wrapper {
    width: 90%; /* Make the form take up most of the width on small screens */
  }
}
</style>
